import base64
import hashlib
import hmac
import time
import urllib.parse
from dingtalkchatbot.chatbot import DingtalkChatbot, FeedLink

from src.config_util import Config
from src.common import JenkinsUtil, now_time


class DingTalkSend:
    """ 发送钉钉通知 """

    def __init__(self, metrics):
        self.metrics = metrics
        self.timeStamp = str(round(time.time() * 1000))
        self.conf = Config()
        self.webhook = self.conf.get_conf("ding_talk").get("webhook")
        self.secret = self.conf.get_conf("ding_talk").get("secret")
        self.jenkins_info = JenkinsUtil()

    def xiao_ding(self):
        sign = self.get_sign()
        # 从yaml文件中获取钉钉配置信息
        webhook = self.webhook + "&timestamp=" + self.timeStamp + "&sign=" + sign
        return DingtalkChatbot(webhook)

    def get_sign(self):
        """
        根据时间戳 + "sign" 生成密钥
        :return:
        """
        string_to_sign = f'{self.timeStamp}\n{self.secret}'.encode('utf-8')
        hmac_code = hmac.new(
            self.secret.encode('utf-8'),
            string_to_sign,
            digestmod=hashlib.sha256).digest()

        sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
        return sign

    def send_text(self, msg, mobiles=None):
        """
        发送文本信息
        :param msg: 文本内容
        :param mobiles: 艾特用户电话
        :return:
        """
        if not mobiles:
            self.xiao_ding().send_text(msg=msg, is_at_all=True)
        else:
            if isinstance(mobiles, list):
                self.xiao_ding().send_text(msg=msg, at_mobiles=mobiles)
            else:
                raise TypeError("mobiles类型错误 不是list类型.")

    def send_link(self, title, text, message_url, pic_url):
        """
        发送link通知
        :return:
        """
        self.xiao_ding().send_link(
            title=title,
            text=text,
            message_url=message_url,
            pic_url=pic_url
        )

    def send_markdown(self, title, msg, mobiles=None, is_at_all=False):
        """

        :param is_at_all:
        :param mobiles:
        :param title:
        :param msg:
        markdown 格式
        """

        if mobiles is None:
            self.xiao_ding().send_markdown(title=title, text=msg, is_at_all=is_at_all)
        else:
            if isinstance(mobiles, list):
                self.xiao_ding().send_markdown(title=title, text=msg, at_mobiles=mobiles)
            else:
                raise TypeError("mobiles类型错误 不是list类型.")

    @staticmethod
    def feed_link(title, message_url, pic_url):
        """ FeedLink 二次封装 """
        return FeedLink(
            title=title,
            message_url=message_url,
            pic_url=pic_url
        )

    def send_feed_link(self, *arg):
        """发送 feed_lik """

        self.xiao_ding().send_feed_card(list(arg))

    def send(self):
        """ 发送钉钉报告通知 """
        # 判断如果有失败的用例，@所有人
        is_at_all = False
        if self.metrics.failed + self.metrics.error > 0:
            is_at_all = True
        text = f"\n\n>项目名称: {self.metrics.job_name}\n\n>" \
               f"\n\n>构建编号: {self.metrics.build_number}" \
               f"\n\n>测试环境: {self.conf.get_conf('env')}" \
               f"\n\n>测试报告: {self.metrics.allure_url}" \
               f"\n\n>构建地址: {self.metrics.build_url}" \
               f"\n\n>用例总数: {self.metrics.total}" \
               f"\n\n>成功用例数: {self.metrics.passed}" \
               f"\n\n>失败用例数: {self.metrics.failed}" \
               f"\n\n>异常用例数: {self.metrics.error}" \
               f"\n\n>跳过用例数: {self.metrics.skipped}" \
               f"\n\n>通过率: {self.metrics.pass_rate}%" \
               f"\n\n>失败用例: {self.metrics.failed_cases}" \
               f"\n\n>用例执行时长: {self.metrics.duration}" \
               f"\n\n>通知时间: {now_time()}\n"

        self.send_markdown(
            title="【自动化测试结果通知】",
            msg=text,
            is_at_all=is_at_all
        )
